
unit texture_manager;

{$mode objfpc}{$H+}{$J-}

interface

uses sdl2, fgl, SysUtils, glog, sdl2_image;

type
  TTextureDict = specialize TFPGMap<string, PSDL_Texture>;

  TTextureManager = class
  private
    textureMap: TTextureDict;
    constructor Init;
  public
    class function Instance: TTextureManager;
    destructor Destroy(); override;
    function QueryTexture(id: string; format: puint32;
      access, Width, Height: pint32): integer;

    function Load(pr: PSDL_Renderer; id, filename: string): boolean;
    procedure Draw(pr: PSDL_Renderer; id: string; x, y, w, h: integer;
      scale: single = 1.0; angle: single = 0; flip: integer = 0);
    procedure DrawFrame(pr: PSDL_Renderer; id: string;
      x, y, w, h, row, frame: integer; scale: single = 1.0; angle: single = 0;
      flip: integer = 0);
  end;

implementation

var
  m: TTextureManager = nil;

function TTextureManager.QueryTexture(id: string; format: puint32;
  access, Width, Height: pint32): integer;
begin
  Result := SDL_QueryTexture(textureMap[id], format, access, Width, Height);
end;

destructor TTextureManager.Destroy;
var
  i: integer;
  id: string;
begin
  for i := 0 to textureMap.Count - 1 do
  begin
    id := textureMap.Keys[i];
    SDL_DestroyTexture(textureMap[id]);
  end;
  FreeAndNil(textureMap);
end;

constructor TTextureManager.Init;
begin
  inherited Create;
  textureMap := TTextureDict.Create;
end;

class function TTextureManager.Instance: TTextureManager;
begin
  if m = nil then
    m := TTextureManager.Init;
  Result := m;
end;

function TTextureManager.Load(pr: PSDL_Renderer; id, filename: string): boolean;

var
  pt: PSDL_Texture;
begin
  if texturemap.IndexOf(id) >= 0 then
    exit(True);

  pt := IMG_LoadTexture(pr, PChar(filename));

  if pt = nil then
    exit(False);

  textureMap.Add(id, pt);
  Result := True;
end;

procedure TTextureManager.Draw(pr: PSDL_Renderer; id: string;
  x, y, w, h: integer; scale: single = 1.0; angle: single = 0; flip: integer = 0);

begin
  DrawFrame(pr, id, x, y, w, h, 0, 0, scale, angle, flip);
end;

procedure TTextureManager.DrawFrame(pr: PSDL_Renderer; id: string;
  x, y, w, h, row, frame: integer; scale: single = 1.0; angle: single = 0;
  flip: integer = 0);

var
  srcRect: TSDL_Rect;
  destRect: TSDL_Rect;
begin
  srcRect.x := w * frame;
  srcRect.y := h * (row);
  srcRect.w := w;
  srcRect.h := h;

  destRect.x := round(x + (w - w * scale) / 2);
  destRect.y := round(y + (y - y * scale) / 2);
  destRect.w := round(w * scale);
  destRect.h := round(h * scale);
  SDL_RenderCopyEx(pr, textureMap.KeyData[id], @srcRect, @destRect, angle, nil, flip);

end;

end.
